//
// Created by Administrator on 2021/10/22.
//

#include "OrthoCamera.h"

//OrthoCamera::OrthoCamera() {
//    type = GET_CLASS(__FILE__);
//    name = type + "_" + id;
//
//    this->left = -1.0f/2.0f * (float) WINDOW_WIDTH;
//    this->right = 1.0f/2.0f * (float) WINDOW_WIDTH;
//    this->bottom = -1.0f/2.0f * (float) WINDOW_HEIGHT;
//    this->top = 1.0f/2.0f * (float) WINDOW_HEIGHT;
//    this->nearplan = 0.3f;
//    this->farplan = 2000.0f;
//}


OrthoCamera::OrthoCamera(float width, float height, float depth) {
    type = GET_CLASS(__FILE__);
    name = type + "_" + id;

    this->left = 0;
    this->right = width;
    this->bottom = 0;
    this->top = height;
    this->nearplan = 0;
    this->farplan = depth;

    target = Vector3(0.0f, 0.0f, -1.0f);
}

OrthoCamera::OrthoCamera(const float left, const float right, const float bottom, const float top, const float nearplan,
                         const float farplan) {
    type = GET_CLASS(__FILE__);
    name = type + "_" + id;

    this->left = left;
    this->right = right;
    this->bottom = bottom;
    this->top = top;
    this->nearplan = nearplan;
    this->farplan = farplan;

    target = Vector3(0.0f, 0.0f, -1.0f);
}


/**
 * 获得投影矩阵
 * @return 矩阵
 */
Matrix4x4 OrthoCamera::getProjectionMatrix() {
    return Matrix4x4::orthographic(left, right, bottom, top, nearplan, farplan);
}

/**
* 获得视图矩阵
* @return 矩阵
*/
Matrix4x4 OrthoCamera::getViewMatrix() {
    Matrix4x4 cameraMat = Matrix4x4::lookAt(location, target, up);
    //逆矩阵
    Matrix4x4 viewMat = cameraMat.inverse();
    return viewMat;
}

void OrthoCamera::onInit() {
    if(!geometries.empty()) {
        for (auto iterator = geometries.begin(); iterator != geometries.end(); iterator ++) {
            if (NULL != *iterator) {
                SAFE_DELETE(*iterator);
            }
        }
        std::vector<BufferGeometry *>().swap(geometries);
    }

    //helper.. todo, 到时候要放在外边动态计算，不能再初始化就处理
    BufferGeometry *helper = new OrthoCameraHelper(location, up, left, right, bottom, top, nearplan, farplan);
    geometries.push_back(helper);

    // 坐标系
    //原点 Location
    //z方向
    Vector3 zDir = location - target;
    zDir.normalize();
    //x方向
    Vector3 xDir = Vector3::crossProduct(zDir, up);
    xDir.normalize();
    //y方向
    Vector3 yDir = Vector3::crossProduct(zDir, xDir);
    yDir.normalize();

    AxiesBufferGeometry * axiesBufferGeometry = new AxiesBufferGeometry(location, xDir, yDir, zDir);
    geometries.push_back(axiesBufferGeometry);

    Camera::onInit();
}

void OrthoCamera::getUI() {
    Camera::getUI();

    bool refreshAttri = false;
    if(ImGui::DragFloat3("Target", &target.x, 0.01f)){
        refreshAttri = true;
    }
    if(ImGui::InputFloat3("Up", &up.x)){
        refreshAttri = true;
    }

    if(refreshAttri){ // todo 等待优化
        onInit();
    }
}


